import { Injectable, Inject, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { SchedulerRegistry } from '@nestjs/schedule';
import { Model } from 'mongoose';
import { Task, TaskDocument } from './schemas/task.schema';
import { CronJob } from 'cron';
import * as os from 'os';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { Connection } from 'mongoose';
import { InjectConnection } from '@nestjs/mongoose';
import { CreateTaskDto } from './dto/create-task.dto';
import { UpdateTaskDto } from './dto/update-task.dto';

@Injectable()
export class SystemInfoService {
  constructor(
    @InjectModel(Task.name) private taskModel: Model<TaskDocument>,
    private schedulerRegistry: SchedulerRegistry,
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    @InjectConnection() private connection: Connection,
  ) {
    // 初始化时从数据库加载定时任务
    this.initTasksFromDatabase();
  }

  private async initTasksFromDatabase() {
    try {
      const tasks = await this.taskModel.find({ isActive: true }).exec();
      tasks.forEach(task => {
        this.addCronJob(task.name, task.cronExpression);
      });
    } catch (error) {
      console.error('Failed to initialize tasks from database:', error);
    }
  }

  // Redis数据查看
  async getRedisKeys(pattern: string = '*'): Promise<string[]> {
    // 这里需要直接使用Redis客户端的keys命令，因为cache-manager不直接暴露此功能
    // 这里使用了一个技巧，通过存储一个临时键并获取所有键来实现
    const redis = await (this.cacheManager as any).store.getClient();
    return new Promise((resolve, reject) => {
      redis.keys(pattern, (err, keys) => {
        if (err) reject(err);
        else resolve(keys);
      });
    });
  }

  async getRedisValue(key: string): Promise<any> {
    return this.cacheManager.get(key);
  }

  async setRedisValue(key: string, value: any, ttl?: number): Promise<void> {
    await this.cacheManager.set(key, value, ttl);
  }

  async deleteRedisKey(key: string): Promise<void> {
    await this.cacheManager.del(key);
  }

  // 定时任务管理
  async getAllTasks(): Promise<Task[]> {
    return this.taskModel.find().sort({ createdAt: -1 }).exec();
  }

  async getTask(id: string): Promise<Task> {
    const task = await this.taskModel.findById(id).exec();
    if (!task) {
      throw new NotFoundException(`任务ID ${id} 不存在`);
    }
    return task;
  }

  async createTask(createTaskDto: CreateTaskDto): Promise<Task> {
    const createdTask = new this.taskModel(createTaskDto);
    
    if (createTaskDto.isActive) {
      this.addCronJob(createTaskDto.name, createTaskDto.cronExpression);
    }
    
    return createdTask.save();
  }

  async updateTask(id: string, updateTaskDto: UpdateTaskDto): Promise<Task> {
    const task = await this.taskModel.findById(id).exec();
    if (!task) {
      throw new NotFoundException(`任务ID ${id} 不存在`);
    }
    
    // 如果更改了cron表达式或激活状态，需要重新设置任务
    if (task.isActive && this.schedulerRegistry.getCronJobs().has(task.name)) {
      this.schedulerRegistry.deleteCronJob(task.name);
    }
    
    if (updateTaskDto.isActive && updateTaskDto.cronExpression) {
      this.addCronJob(task.name, updateTaskDto.cronExpression);
    }
    
    const updatedTask = await this.taskModel.findByIdAndUpdate(id, updateTaskDto, { new: true }).exec();
    if (!updatedTask) {
      throw new NotFoundException(`任务ID ${id} 不存在`);
    }
    return updatedTask;
  }

  async deleteTask(id: string): Promise<void> {
    const task = await this.taskModel.findById(id).exec();
    if (!task) {
      throw new NotFoundException(`任务ID ${id} 不存在`);
    }
    
    if (task.isActive && this.schedulerRegistry.getCronJobs().has(task.name)) {
      this.schedulerRegistry.deleteCronJob(task.name);
    }
    
    await this.taskModel.findByIdAndDelete(id).exec();
  }

  private addCronJob(name: string, cronExpression: string) {
    const job = new CronJob(cronExpression, () => {
      this.handleCron(name);
    });
    
    this.schedulerRegistry.addCronJob(name, job as any);
    job.start();
  }

  private async handleCron(taskName: string) {
    console.log(`Task ${taskName} executed at ${new Date()}`);
    // 更新任务最后运行时间
    await this.taskModel.findOneAndUpdate(
      { name: taskName },
      { 
        lastRunTime: new Date(),
        nextRunTime: this.getNextRunTime(taskName)
      }
    ).exec();
    
    // 这里可以实现具体的任务逻辑，或者调用其他服务
  }

  private getNextRunTime(taskName: string): Date {
    const job = this.schedulerRegistry.getCronJob(taskName);
    return (job.nextDate() as any).toJSDate();
  }

  // 数据库信息
  async getDatabaseInfo(): Promise<any> {
    const dbInfo = {
      connection: {
        host: this.connection.host,
        port: this.connection.port,
        name: this.connection.name,
        readyState: this.connection.readyState,
      },
      collections: {},
      stats: await this.connection.db!.stats(),
    };
    
    // 获取所有集合
    const collections = await this.connection.db!.listCollections().toArray();
    
    // 获取每个集合的文档数
    for (const collection of collections) {
      const count = await this.connection.db!.collection(collection.name).countDocuments();
      dbInfo.collections[collection.name] = { count };
    }
    
    return dbInfo;
  }

  // 系统信息
  getSystemInfo(): any {
    return {
      hostname: os.hostname(),
      platform: os.platform(),
      architecture: os.arch(),
      cpus: os.cpus(),
      totalMemory: os.totalmem(),
      freeMemory: os.freemem(),
      uptime: os.uptime(),
      loadavg: os.loadavg(),
      networkInterfaces: os.networkInterfaces(),
      nodeVersion: process.version,
      processUptime: process.uptime(),
      processMemoryUsage: process.memoryUsage(),
    };
  }
} 